package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"

	//"smartu365.com/protocol808"
	"server/src/protocol808"
)

const (
	CommandSuccess int = 0
	CommandFaild   int = 1
)

type CommandHTTPServer struct {
	cfg        *Config
	manager    *ConnManager
	dbo        *DBOperation
	whiteLists *HTTPWhiteLists
	serialNo   uint16
}

func NewCommandHTTPServer(config *Config, dbo *DBOperation, connManager *ConnManager) *CommandHTTPServer {
	c := CommandHTTPServer{cfg: config, dbo: dbo, manager: connManager}
	c.whiteLists = NewHTTPWhiteLists(dbo)
	return &c
}

func (p *CommandHTTPServer) Listen() {
	sPort := fmt.Sprintf(":%d", p.cfg.CommandHttpPort)

	http.HandleFunc("/count", p.Count)
	http.HandleFunc("/receiver/bindsensor", p.ReceiverBindSensor)

	http.HandleFunc("/receiver/setfrequncy", p.SetFrequency)
	http.HandleFunc("/receiver/setdevicesleep", p.SetDeviceSleep)
	http.HandleFunc("/receiver/disconnect", p.DisconnectReceiver)

	zLog(nil, "接收器服务器开始监听指令下发HTTP端口:", sPort)
	//go http.ListenAndServe(sPort, nil)
	go func() {
		zLog(nil, "开始监听端口:", sPort, " HTTPS:", p.cfg.HTTPS)
		var err error
		if p.cfg.HTTPS {
			err = http.ListenAndServeTLS(sPort, p.cfg.CertFile, p.cfg.KeyFile, nil)
		} else {
			err = http.ListenAndServe(sPort, nil)
		}
		if err != nil {
			zLog(nil, "监听端口:", sPort, "失败:", err)
		}
	}()
}

type BindSensorT struct {
	Sid    string `json:"sid"`
	CardId int    `json:"cardid"`
	SN     int    `json:"sn"`
}
type ReceiverBindSensorT struct {
	Rid     string        `json:"rid"`
	RType   int           `json:"type"`
	Mode    int           `json:"mode"`
	Sensors []BindSensorT `json:"sensors"`
}

func (p *CommandHTTPServer) ReceiverBindSensor(w http.ResponseWriter, req *http.Request) {
	zLog(nil, "ReceiverBindSensor start......")
	if p.checkLocal(req.RemoteAddr) {
		buf, ok := p.readBody(&w, req)
		if ok {
			var rbs ReceiverBindSensorT
			err := json.Unmarshal(buf, &rbs)
			if err != nil {
				w.Write([]byte(err.Error()))
				return
			}

			p.serialNo++
			bindSendor := protocol808.CommandBindSensorToPosition{}
			bindSendor.Sensors = make([]protocol808.SensorPositionT, 0)
			bindSendor.TerminalId = rbs.Rid
			bindSendor.CommandId = protocol808.CommandIdBindTireToPosition
			if rbs.Mode == 1 {
				// 提交对码
				bindSendor.OperateModel = protocol808.CommandOperateModelSet
			} else if rbs.Mode == 2 {
				// 删除对码
				bindSendor.OperateModel = protocol808.CommandOperateModelDelete
			} else if rbs.Mode == 3 {
				// 查询对码
				bindSendor.OperateModel = protocol808.CommandOperateModelQuery
			} else if rbs.Mode == 4 {
				// 立刻对码
				bindSendor.OperateModel = protocol808.CommandOperateModelMatchImmediately
			} else if rbs.Mode == 5 {
				// 自动对码
				bindSendor.OperateModel = protocol808.CommandOperateModelMatchAuto
			}
			bindSendor.SerialNo = p.serialNo

			var tempSid string
			for _, v := range rbs.Sensors {
				if rbs.Mode == 1 {
					tempSid = v.Sid
				} else {
					tempSid = ""
				}
				sensor := protocol808.SensorPositionT{SensorId: tempSid, CardId: v.CardId, SerialNo: v.SN}
				bindSendor.Sensors = append(bindSendor.Sensors, sensor)
			}

			message, command := bindSendor.Pack()
			err = p.SendCommand(rbs.Rid, p.serialNo, message, command)

			var sResult string
			if err == nil {
				sResult = p.makeResultStr(CommandSuccess, "设置成功")
			} else {
				sResult = p.makeResultStr(CommandFaild, "设置失败")
			}
			w.Write([]byte(sResult))
		}
	} else {
		w.Write([]byte("Just for local IP"))
	}
}

/*

type ThresholdT struct {
	Pressure    [5][2]float32 `json:"pressure"`
	Temperature int           `json:"temperature"`
}

type ReceiverThresholdT struct {
	Rid       string     `json:"rid"`
	Threshold ThresholdT `json:"threshold"`
}

func (p *CommandHTTPServer) SetTireThreshold(w http.ResponseWriter, req *http.Request) {
	if p.checkLocal(req.RemoteAddr) {
		buf, ok := p.readBody(&w, req)
		if ok {
			var rt ReceiverThresholdT
			err := json.Unmarshal(buf, &rt)
			if err != nil {
				w.Write([]byte(err.Error()))
				return
			}


			p.serialNo++
			threshold := protocol808.CommandYatTirePressure{}
			threshold.TerminalId = rt.Rid
			threshold.SerialNo = p.serialNo
			threshold.Threshold.Temperature = rt.Threshold.Temperature
			for i := 0; i < 5; i++ {
				threshold.Threshold.Pressures[i][0], threshold.Threshold.Pressures[i][1] = rt.Threshold.Pressure[i][0], rt.Threshold.Pressure[i][1]
			}

			message, command := threshold.Pack()
			err = p.SendCommand(rt.Rid, p.serialNo, message, command)

			var sResult string
			if err == nil {
				sResult = p.makeResultStr(CommandSuccess, "设置成功")
			} else {
				sResult = p.makeResultStr(CommandFaild, "设置失败")
			}
			w.Write([]byte(sResult))
		}
	} else {
		w.Write([]byte("Just for local IP"))
	}
}
*/

type UploadFrequncyT struct {
	Rid      string `json:"rid"`
	TireData int    `json:"tiredata"`
	GPS      int    `json:"gps"`
}

func (p *CommandHTTPServer) SetFrequency(w http.ResponseWriter, req *http.Request) {
	if p.checkLocal(req.RemoteAddr) {
		buf, ok := p.readBody(&w, req)
		if ok {
			var uf UploadFrequncyT
			err := json.Unmarshal(buf, &uf)
			if err != nil {
				w.Write([]byte(err.Error()))
				return
			}
			var sResult string

			p.serialNo++
			frequncy := protocol808.CommandSetUploadFrequncy{}
			frequncy.TerminalId = uf.Rid
			frequncy.SerialNo = p.serialNo
			frequncy.GPSInterval = uf.GPS
			frequncy.TireDataInterval = uf.TireData

			message, command := frequncy.Pack()
			err = p.SendCommand(uf.Rid, p.serialNo, message, command)

			if err == nil {
				sResult = p.makeResultStr(CommandSuccess, "设置成功")
			} else {
				sResult = p.makeResultStr(CommandFaild, "设置失败")
			}
			w.Write([]byte(sResult))
		}
	} else {
		w.Write([]byte("Just for local IP"))
	}
}

type DeviceSleepT struct {
	Rid         string `json:"rid"`
	DeviceSleep int    `json:"devicesleep"`
}

func (p *CommandHTTPServer) SetDeviceSleep(w http.ResponseWriter, req *http.Request) {
	if p.checkLocal(req.RemoteAddr) {
		buf, ok := p.readBody(&w, req)
		if ok {
			var ds DeviceSleepT
			err := json.Unmarshal(buf, &ds)
			if err != nil {
				w.Write([]byte(err.Error()))
				return
			}
			var sResult string

			p.serialNo++
			deviceSleep := protocol808.CommandSetDeviceSleep{}
			deviceSleep.TerminalId = ds.Rid
			deviceSleep.SerialNo = p.serialNo
			deviceSleep.DeviceSleep = ds.DeviceSleep

			message, command := deviceSleep.Pack()
			err = p.SendCommand(ds.Rid, p.serialNo, message, command)

			if err == nil {
				sResult = p.makeResultStr(CommandSuccess, "设置成功")
			} else {
				sResult = p.makeResultStr(CommandFaild, "设置失败")
			}
			w.Write([]byte(sResult))
		}
	} else {
		w.Write([]byte("Just for local IP"))
	}
}

func (p *CommandHTTPServer) DisconnectReceiver(w http.ResponseWriter, req *http.Request) {
	if p.checkLocal(req.RemoteAddr) {
		req.ParseForm()
		rids := req.FormValue("rids")
		if p.checkFields(&w, rids) {
			var sResult, rid string
			var conn *ReceiverConnection

			arrayRid := strings.Split(rids, ",")
			for i := 0; i < len(arrayRid); i++ {
				rid = arrayRid[i]
				if len(rid) == 12 {

					conn = p.manager.Get(rid)
					if conn != nil {
						sResult += rid + ","
						conn.Disconnect()
					}
				}
			}

			sResult = p.makeResultStr(0, sResult+"已断开")
			w.Write([]byte(sResult))
		}
	} else {
		w.Write([]byte("Just for local IP"))
	}
}

func (p *CommandHTTPServer) SendCommand(rid string, serialNo uint16, message string, command string) error {
	p.dbo.SaveCommand(rid, serialNo, message, command)
	/*
		var err error

		conn := p.manager.Get(rid)
		if conn == nil {
			zLog(nil, rid, "当前不在线，命令已保存到数据库中")

		} else {
			buf := conn.hexStr2Bytes(message)
			err = conn.SafeSend(buf)
			if err == nil {
				zLog(conn.conn, rid, "下发指令：", message, " 成功")
				go p.dbo.SetCommandStatus(oid, CommandStatusSent)
			} else {
				zLog(conn.conn, rid, "下发指令：", message, " 失败：", err.Error())
			}
		}
	*/
	return nil
}

func (p *CommandHTTPServer) Count(w http.ResponseWriter, req *http.Request) {
	zLog(nil, "Count start......")
	if p.checkLocal(req.RemoteAddr) {
		s := fmt.Sprintf(`{"count":%d}`, p.manager.Count())
		w.Write([]byte(s))
	} else {
		w.Write([]byte("Just for local IP"))
	}
}

/*

func (p *CommandHTTPServer) commonCheck(w *http.ResponseWriter, req *http.Request) bool {
	(*w).Header().Add("Access-Control-Allow-Origin", "*")

	var s string
	if req.Method != "POST" {
		s = p.makeResultStr(0, "无效的访问方式")
		(*w).Write([]byte(s))
		return false
	}

	ip := req.RemoteAddr
	if !p.whiteLists.Exists(ip) {
		ip = p.whiteLists.trimIP(ip)
		s = p.makeResultStr(0, ip+" 不在白名单中，请与管理人员联系")
		(*w).Write([]byte(s))
		return false
	}
	return true
}
*/

func (p *CommandHTTPServer) checkLocal(ip string) bool {
	index := strings.Index(ip, ":")
	if index >= 0 {
		ip = ip[0:index]
	}
	zLog(nil, "访问IP：", ip)
	return ip == "127.0.0.1"
}

func (p *CommandHTTPServer) checkFields(w *http.ResponseWriter, fields ...string) bool {
	for _, field := range fields {
		if field == "" {
			s := p.makeResultStr(1003, "缺少必要的字段")
			(*w).Write([]byte(s))
			return false
		}
	}
	return true
}

func (p *CommandHTTPServer) makeResultStr(code int, msg string) string {
	return fmt.Sprintf(`{"errcode":%d,"msg":"%s"}`, code, msg)
}

func (p *CommandHTTPServer) readBody(w *http.ResponseWriter, req *http.Request) ([]byte, bool) {
	buf, err := ioutil.ReadAll(req.Body)
	defer req.Body.Close()

	if err != nil || buf == nil {
		sErr := p.makeResultStr(ResultFaild, "内容为空，无效请求")
		(*w).Write([]byte(sErr))
		return nil, false
	}

	return buf, true
}
